package com.tan.lighting.disruptor.handler;

import com.lmax.disruptor.EventHandler;
import com.tan.lighting.ddd.Command;
import com.tan.lighting.disruptor.Handler;
import com.tan.lighting.disruptor.event.CommandEvent;
import com.tan.lighting.disruptor.snapshot.Snapshot;
import com.tan.lighting.disruptor.snapshot.factory.SnapshotFactory;
import com.tan.lighting.disruptor.snapshot.utils.SnapshotFileUtil;
import com.tan.lighting.disruptor.snapshot.utils.SnapshotJsonUtil;
import com.tan.lighting.file.JournalFile;
import com.tan.lighting.nio.ByteBufferSerializer;
import com.tan.lighting.nio.ReuseByteBuffer;

import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * Description:记录命令日志的handler。 将命令写入本地；做snapshot
 * User: tan
 * DateTime: 2018/1/3 17:29
 */
public class JournalCommandHandler implements EventHandler<CommandEvent> {
    protected SnapshotFactory snapshotFactory;
    protected String fileBasePath;
    protected String jFileNamePrefix;

    protected JournalFile jFile;
    protected ReuseByteBuffer reuseByteBuffer;

    @Override
    public void onEvent(CommandEvent event, long sequence, boolean endOfBatch) throws Exception {
        if (jFile == null) {

            String recentFileName = SnapshotFileUtil.getRecentFileName(".", jFileNamePrefix);
            if (recentFileName == null || recentFileName.equals("")) {
                recentFileName = jFileNamePrefix + System.currentTimeMillis();
            }
            jFile = new JournalFile(recentFileName);
            reuseByteBuffer = new ReuseByteBuffer(ByteBuffer.allocateDirect(1024 * 1024));
        }
        if (!event.isSnapshot()) {
            Command cmd = event.getCmd();
            Handler handler = event.getHandler();
            if (handler != null) {
                recordJournalFile(cmd);
            }
        } else {
            try {
                saveSnapshot();
                jFile.close();
                jFile = new JournalFile(jFileNamePrefix + System.currentTimeMillis());
            } catch (Throwable e) {
                System.out.println("System.exit(0)  " + e.getMessage());
                System.exit(0);// 任何失败系统停机。
            }
        }
    }

    private void recordJournalFile(Command cmd) {
        ByteBuffer bb = reuseByteBuffer.take();
        try {
            ByteBufferSerializer.objToByteBuffer(cmd, bb);
            jFile.write(bb);
        } catch (Throwable e) {
            System.exit(0);// 任何失败系统停机。
        }
    }

    private void saveSnapshot() throws IOException {
        Snapshot snapshoot = snapshotFactory.createSnapshoot();
        SnapshotJsonUtil.save(fileBasePath, snapshoot.getCreateTime() + "", snapshoot);
    }
}
